/**
 * @program: clms-second
 * @description:
 * @author: mitu_echo
 * @create: 2021-07-22 15:51
 **/

package com.second.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.second.common.pojo.R;
import com.second.common.util.JwtUtil;
import com.second.common.util.Payload;
import com.second.system.config.RsaKeyProperties;
import com.second.system.dao.UserDao;
import com.second.system.pojo.entity.Logininfo;
import com.second.system.pojo.entity.User;
import com.second.system.pojo.utils.IPUtils;
import com.second.system.pojo.utils.MyAnnotation;
import com.second.system.pojo.utils.WebUtil;
import com.second.system.pojo.vo.LoginVo;
import com.second.system.pojo.vo.ShowAllUserVO;
import com.second.system.service.LogininfoService;
import com.second.system.service.UserService;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;
    @Autowired
    private RsaKeyProperties rsaKeyProperties;
    @Autowired
    private LogininfoService logininfoService;

    @Override
    public User queryUserByName(String loginname) {

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("loginname",loginname);
        queryWrapper.eq("status",0);
        User user = userDao.selectOne(queryWrapper);
        return user;
    }

    @Override
    public R doLogin(LoginVo loginVo) {
        UsernamePasswordToken token = new UsernamePasswordToken(loginVo.getLoginname(),loginVo.getUserpwd());
        Subject subject = SecurityUtils.getSubject();
        // 获取 ip 地址
        String ipAddr = IPUtils.getIpAddr(WebUtil.getRequest());
        try {
            // 会进入UserRealm重写的认证方法中
            subject.login(token);
        } catch (UnknownAccountException uae) {
            // 用户名不存在抛出异常
            R r = R.error();
            r.setMessage("当前用户不存在");
            logininfoService.addLogininfo(loginVo.getLoginname(),ipAddr,'1');
            return r;
        } catch (IncorrectCredentialsException ice) {
            // 用户密码错误异常
            R r = R.error();
            r.setMessage("密码输入错误");
            logininfoService.addLogininfo(loginVo.getLoginname(),ipAddr,'1');
            return r;
        }
        // 登录成功之后获取用户信息
        User user =(User) subject.getPrincipal();
        user.setLoginIp(ipAddr);
        user.setLoginDate(LocalDateTime.now().toString());
        // 修改用户的登录时间
        userDao.updateById(user);
        // 添加登录信息表中的数据
        logininfoService.addLogininfo(loginVo.getLoginname(),ipAddr,'0');
        // 将用户的密码置空
        user.setUserpwd("");
        // 根据私钥和用户信息，设置当前用户的 token
        String userToken = JwtUtil.generateTokenExpireInMinutes(user, rsaKeyProperties.getPrivatekey(), 24 * 60);
        // 将 token 写入返回结果，返回给前端
        R r = R.success();
        r.setMessage("登录成功");
        r.setToken(userToken);
        return r;
    }

    @Override
    @MyAnnotation( title = "用户模块",businessType = 0)
    public R getUserInfo() {

        // 获取 token
        String token = WebUtil.getRequest().getHeader("Token");
        // 解析token
        Payload<User> infoFromToken = JwtUtil.getInfoFromToken(token, rsaKeyProperties.getPublicKey(), User.class);
        // 获取用户信息
        User userInfo = infoFromToken.getUserInfo();
        return R.success().putObject(userInfo);
    }

    @Override
    @MyAnnotation( title = "用户模块",businessType = 0)
    public R showAllUser(ShowAllUserVO showAllUserVO) {

        QueryWrapper queryWrapper = new QueryWrapper();
        if (StringUtils.isNotEmpty(showAllUserVO.getLoginname())) {
            queryWrapper.like("loginname",showAllUserVO.getLoginname());
        }
        if (StringUtils.isNotEmpty(showAllUserVO.getUsername())) {
            queryWrapper.like("username",showAllUserVO.getUsername());
        }
        if (StringUtils.isNotEmpty(showAllUserVO.getEmail())) {
            queryWrapper.like("email",showAllUserVO.getEmail());
        }
        if (StringUtils.isNotEmpty(showAllUserVO.getPhone())) {
            queryWrapper.like("phone",showAllUserVO.getPhone());
        }
        PageHelper.startPage(showAllUserVO.getPageno(),showAllUserVO.getPagesize());
        List userList = userDao.selectList(queryWrapper);
        PageInfo pageInfo = new PageInfo(userList);
        return R.success().putObject(pageInfo).putListData(userList);
    }

    @Override
    @MyAnnotation( title = "用户模块",businessType = 1)
    public R addUser(User user) {

        // 先判断当前添加的用户登录名是否已经存在
        User u = queryUserByName(user.getLoginname());
        if (u != null) {
            R r = R.error();
            r.setMessage("当前添加用户已经存在");
            return r;
        }
        // 现将当前用户的密码进行加密
        Md5Hash userpwd = new Md5Hash(user.getUserpwd(),"efdd1d36-2430-4",2);
        user.setUserpwd(userpwd.toString());
        // 设置用户盐值
        user.setSalt("efdd1d36-2430-4");
        int i = userDao.insert(user);
        if (i>0) {
            return R.success();
        }
        return R.error();
    }

    @Override
    @MyAnnotation( title = "用户模块",businessType = 3)
    public R delUserByUserid(Integer userid) {

        int i = userDao.deleteById(userid);
        if (i>0) {
            return R.success();
        }
        return R.error();
    }

    @Override
    @MyAnnotation( title = "用户模块",businessType = 2)
    public R updateUser(User user) {

        user.setUserpwd(null);
        int i = userDao.updateById(user);
        if (i>0) {
            return R.success();
        }
        return R.error();
    }

    @Override
    @MyAnnotation( title = "用户模块",businessType = 2)
    public R updateStatus(Integer userid, Character status) {

        User user = new User();
        user.setUserid(userid);
        user.setStatus(status);
        int i = userDao.updateById(user);
        if (i>0) {
            return R.success();
        }
        return R.error();
    }

    @Override
    @MyAnnotation( title = "用户模块",businessType = 2)
    public R updatePwd(String userpwd) {

        // 获取 token
        String token = WebUtil.getRequest().getHeader("Token");
        // 解析token
        Payload<User> infoFromToken = JwtUtil.getInfoFromToken(token, rsaKeyProperties.getPublicKey(), User.class);
        // 获取用户信息
        User userInfo = infoFromToken.getUserInfo();
        // 创建新的user对象
        User user = new User();
        // 设置用户的 id
        user.setUserid(userInfo.getUserid());
        // 将铭文密码进行加密
        Md5Hash newPwd = new Md5Hash(userpwd,userInfo.getSalt(),2);
        user.setUserpwd(newPwd.toString());
        int i = userDao.updateById(user);
        if (i>0) {
            return R.success();
        }
        return R.error();
    }
}
